import { useEffect, useState } from 'react'
import styles from './scss/ImageUpscaleRightContent.module.scss'
import ImageUpscaleManager from '@/lib/imageUpscale/ImageUpscaleManager'
import {
  UpscaleModel,
  RunBack,
  LoadStatus,
  ModelInfo,
} from '@/lib/imageUpscale/types'
import { showToast } from '@/utils/toast'
import { MessageBox } from '@/utils/messageBox'
import {
  explainBlockSize,
  explainCompressionRatio,
  explainModel,
  explainRunBack,
  modelDetails,
  runBackList,
  saveTypes,
} from '@/lib/imageUpscale/common'
import { showLoading } from '@/utils/loading'
import { isMobile, isSaveWebpSupported } from '@/utils/adaptation'
import {
  imagePreviewModes,
  imageUpscaleConfigStore,
  UpscaleModelConfig,
} from '@/store/imageUpscaleConfig'

interface Props {
  onConfigChange: (config: UpscaleModelConfig) => void
  mobileBack: () => any
}

function Question(props: { onClick?: React.MouseEventHandler<SVGSVGElement> }) {
  return (
    <svg
      onClick={props.onClick}
      className={styles['icon']}
      viewBox="0 0 1024 1024"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
      p-id="12290"
      width="200"
      height="200">
      <path
        d="M931.84 513.536c0 228.864-185.856 414.72-414.72 414.72s-414.72-185.856-414.72-414.72 185.856-414.72 414.72-414.72 414.72 185.344 414.72 414.72z m-413.696-352.256c-188.416 0-353.792 165.376-353.792 353.28 0 195.584 158.208 353.792 353.792 353.792s353.792-158.208 353.792-353.792c0-186.88-163.328-353.28-353.792-353.28z"
        fill="#a1afbf"
        p-id="12291"></path>
      <path
        d="M619.52 330.752c-23.552-24.064-58.368-38.912-96.768-38.912-43.008 0-78.848 17.92-104.448 48.128-23.04 26.112-34.816 62.464-34.816 104.448l53.248 0.512c0-29.184 8.192-52.736 21.504-69.632 14.336-19.968 34.304-30.208 64.512-30.208 25.088 0 45.056 6.656 58.88 20.992 13.312 13.312 20.48 31.744 20.48 55.808 0 16.896-6.144 32.256-17.92 47.616-3.584 4.608-9.728 9.728-20.48 21.504-32.256 29.696-52.224 51.712-60.416 69.632-7.168 14.848-11.264 30.208-11.264 52.736v13.824h51.712v-13.824c1.024-16.896 3.072-30.208 10.752-43.52 7.168-10.24 15.872-19.968 29.184-31.232 26.624-23.552 41.984-37.888 48.128-45.056 17.408-22.528 23.04-45.568 23.04-72.704 0-36.864-12.8-69.632-35.328-90.112zM519.68 668.672c-11.264 0-20.48 3.072-28.16 11.264-7.68 7.168-11.264 16.384-11.264 27.648s3.072 20.48 11.264 28.16c7.68 7.168 16.896 11.264 28.16 11.264s20.48-4.096 28.16-11.264 11.776-16.384 11.776-28.16c0-11.264-4.096-20.48-11.264-27.648-8.192-8.192-17.92-11.264-28.672-11.264z"
        fill="#a1afbf"
        p-id="12292"></path>
    </svg>
  )
}

function ImageUpscaleRightContent(props: Props) {
  const [init, setInit] = useState(false)
  const [backend, setBackend] = useState<RunBack>(RunBack.cpu)
  const [modelList, setModelList] = useState<ModelInfo[]>([])
  const [model, setModel] = useState<UpscaleModel>(UpscaleModel.waifu_2x_noise)
  const [blockSize, setBlockSize] = useState<number>(64)
  const [saveType, setSaveType] =
    useState<UpscaleModelConfig['saveType']>('png')
  const [previewMode, setPreviewMode] =
    useState<(typeof imagePreviewModes)[number]>('smooth')
  const [saveCompressionRatio, setSaveCompressionRatio] = useState<number>(0.92)
  const [managerReady, setManagerReady] = useState(
    ImageUpscaleManager.getReady()
  )
  useEffect(() => {
    setModel(imageUpscaleConfigStore.value.model)
    setBlockSize(imageUpscaleConfigStore.value.blockSize)
    setSaveType(imageUpscaleConfigStore.value.saveType)
    setSaveCompressionRatio(imageUpscaleConfigStore.value.saveCompressionRatio)
    setPreviewMode(imageUpscaleConfigStore.value.previewMode)
    setInit(true)
  }, [])
  useEffect(() => {
    ImageUpscaleManager.getBackend().then(setBackend)
    ImageUpscaleManager.getModelList().then(setModelList)
    const u1 = ImageUpscaleManager.event.on('modelStatusChange', (data) => {
      setModelList((list) => {
        const index = list.findIndex((item) => data.name == item.name)
        if (index == -1) {
          return [...list, data]
        }
        list[index].status = data.status
        return [...list]
      })
    })
    const u2 = ImageUpscaleManager.event.on('modelLoadProgress', (data) => {
      setModelList((list) => {
        const index = list.findIndex((item) => data.name == item.name)
        if (index == -1) {
          return [...list, data]
        }
        list[index] = data
        return [...list]
      })
    })
    const u3 = ImageUpscaleManager.event.on('ready', setManagerReady)
    return () => {
      u1()
      u2()
      u3()
    }
  }, [])
  useEffect(() => {
    if (!init) {
      return
    }
    const data = {
      model,
      blockSize,
      backend,
      saveType,
      saveCompressionRatio,
      previewMode,
    }
    props.onConfigChange(data)
    imageUpscaleConfigStore.set(data)
  }, [
    model,
    blockSize,
    backend,
    saveType,
    saveCompressionRatio,
    previewMode,
    init,
  ])

  useEffect(() => {
    if (saveType === 'webp' && !isSaveWebpSupported()) {
      setSaveType('png')
      showToast('当前浏览器不支持webp格式')
    }
  }, [saveType])
  async function setBackendHandle(newBackend: RunBack) {
    if (backend == newBackend) {
      return
    }
    if (!ImageUpscaleManager.getReady()) {
      showToast('程序加载中，请稍等')
      return
    }
    if (ImageUpscaleManager.getRunning()) {
      showToast('模型正在运行中，请稍后')
      return
    }
    if (newBackend == RunBack.cpu) {
      const flag = await MessageBox.propt(
        '提示',
        'cpu比其他运行驱动运行效率低，你确定要切换吗？'
      )
      if (!flag) return
    }
    const un = showLoading('切换中')
    const falg = await ImageUpscaleManager.setBackend(newBackend)
    un()
    if (!falg) {
      if (newBackend != RunBack.webgpu) {
        MessageBox.warn('切换失败', `该设备或浏览器可能并不支持${newBackend}`)
        return
      }
      if (isMobile()) {
        MessageBox.warn(
          '切换失败',
          `该设备或浏览器可能并不支持${newBackend}
目前市面上支持${newBackend}的浏览器有Chrome、Firefox、Safari、微信浏览器。
android版本11以上。`
        )
        return
      }
      MessageBox.warn('切换失败', `该设备或浏览器可能并不支持${newBackend}`)
      return
    }
    setBackend(newBackend)
  }
  async function setModelHandle(model: UpscaleModel) {
    const item = modelList.find((item) => item.name == model)
    switch (item?.status) {
      case LoadStatus.loaded:
        if (ImageUpscaleManager.getRunning()) {
          showToast('模型正在运行中，请稍后')
          return
        }
        setModel(model)
        break
      case LoadStatus.loading:
        showToast('模型正在加载中，请稍后')
        break
      case LoadStatus.error:
        // showToast('模型加载失败，正在重新加载')
        const flag = await MessageBox.propt(
          '提示',
          `模型加载失败，是否重新加载？\n下载模型文件需要${(
            item.loadBytes /
            1024 /
            1024
          ).toFixed(1)}M大小。`
        )
        if (flag) {
          ImageUpscaleManager.requestLoadModel(model)
        }
        break
      case LoadStatus.init: {
        const flag = await MessageBox.propt(
          '提示',
          `模型尚未加载，下载模型文件需要${(
            item.loadBytes /
            1024 /
            1024
          ).toFixed(1)}M大小，是否加载模型？`
        )
        if (flag) {
          ImageUpscaleManager.requestLoadModel(model)
        }
        break
      }
    }
  }
  return (
    <div className={styles['image-upscale-right-content']}>
      <div className={styles['right-line']}></div>
      <svg
        onClick={() => props.mobileBack()}
        className={styles['mobile-back-btn']}
        viewBox="0 0 1126 1024"
        version="1.1"
        xmlns="http://www.w3.org/2000/svg"
        p-id="14829"
        width="200"
        height="200">
        <path
          d="M742.4 0h-358.4C199.68 0 51.2 148.48 51.2 332.8v358.4C51.2 875.52 199.68 1024 384 1024h358.4C926.72 1024 1075.2 875.52 1075.2 691.2v-358.4C1075.2 148.48 926.72 0 742.4 0z m-83.626667 863.573333H296.96c-20.48 0-37.546667-10.24-37.546667-30.72 0-20.48 17.066667-27.306667 37.546667-27.306666h360.106667c92.16 0 192.853333-117.76 192.853333-209.92s-100.693333-197.973333-192.853333-197.973334H317.44l100.693333 93.866667c15.36 15.36 30.72 39.253333 15.36 54.613333-15.36 15.36-35.84 15.36-49.493333 0l-155.306667-157.013333c-11.946667-11.946667-11.946667-30.72-1.706666-42.666667l155.306666-158.72c15.36-15.36 35.84-15.36 49.493334 0 15.36 15.36 0 39.253333-15.36 54.613334L319.146667 341.333333h339.626666c136.533333 0 247.466667 119.466667 247.466667 254.293334 0 138.24-110.933333 267.946667-247.466667 267.946666z"
          fill="#a4b2c1"
          p-id="14830"></path>
      </svg>
      <div
        style={{
          flex: 1,
          overflowY: 'auto',
          boxSizing: 'border-box',
          paddingRight: '10px',
        }}>
        <div className={styles['grop-title']}>
          <span>运行驱动</span>
          <Question onClick={explainRunBack} />
        </div>
        <div className={styles['grop-content']}>
          {runBackList.map((item, index) => {
            return (
              <div
                onClick={() => setBackendHandle(item)}
                key={index}
                className={
                  item == backend
                    ? styles['choice-btn-active']
                    : styles['choice-btn']
                }>
                {item}
              </div>
            )
          })}
        </div>
        <div className={styles['grop-title']}>
          <span>模型</span>
          {!managerReady && (
            <svg
              onClick={() => showToast('模型正在加载中，请稍后')}
              className={styles['icon']}
              viewBox="0 0 1024 1024"
              version="1.1"
              xmlns="http://www.w3.org/2000/svg"
              p-id="3313"
              width="200"
              height="200">
              <path
                d="M768 733.866667c13.653333 13.653333 13.653333 34.133333 0 47.786666-68.266667 68.266667-160.426667 102.4-252.586667 102.4s-180.906667-34.133333-252.586666-102.4c-139.946667-139.946667-139.946667-365.226667 0-505.173333 119.466667-119.466667 303.786667-136.533333 440.32-51.2l-6.826667-81.92c0-20.48 13.653333-34.133333 30.72-37.546667 17.066667 0 34.133333 13.653333 37.546667 30.72l10.24 160.426667c3.413333 30.72-37.546667 47.786667-58.026667 27.306667a286.378667 286.378667 0 0 0-406.186667 0 286.378667 286.378667 0 0 0 0 406.186666c112.64 112.64 293.546667 112.64 406.186667 0 13.653333-10.24 37.546667-10.24 51.2 3.413334z m-150.186667-334.506667l51.2-6.826667c17.066667-3.413333 30.72-20.48 30.72-37.546666-3.413333-17.066667-20.48-30.72-37.546666-30.72l-51.2 6.826666c-17.066667 3.413333-30.72 20.48-30.72 37.546667 3.413333 17.066667 17.066667 30.72 34.133333 30.72h3.413333z"
                fill="#a4b2c1"
                p-id="3314">
                <animateTransform
                  attributeName="transform"
                  attributeType="XML"
                  type="rotate"
                  from="0 512 512"
                  to="360 512 512"
                  dur="1s"
                  repeatCount="indefinite"
                />
              </path>
            </svg>
          )}
        </div>
        <div className={styles['grop-content']}>
          {modelList.map((item) => {
            return (
              <div
                onClick={() => setModelHandle(item.name)}
                key={item.name}
                style={{
                  width: '100%',
                }}
                className={
                  item.name == model
                    ? styles['cell-btn-active']
                    : styles['cell-btn']
                }>
                <div className={styles['cell-btn-wapper']}>
                  <div className={styles['left-content']}>
                    <div className={styles['name']}>{item.name}</div>
                    <div className={styles['span']}>
                      {modelDetails[item.name].name}
                    </div>
                  </div>
                  {item.status == LoadStatus.loading && (
                    <svg
                      className={styles['icon']}
                      viewBox="0 0 1024 1024"
                      version="1.1"
                      xmlns="http://www.w3.org/2000/svg"
                      p-id="3313"
                      width="200"
                      height="200">
                      <path
                        d="M768 733.866667c13.653333 13.653333 13.653333 34.133333 0 47.786666-68.266667 68.266667-160.426667 102.4-252.586667 102.4s-180.906667-34.133333-252.586666-102.4c-139.946667-139.946667-139.946667-365.226667 0-505.173333 119.466667-119.466667 303.786667-136.533333 440.32-51.2l-6.826667-81.92c0-20.48 13.653333-34.133333 30.72-37.546667 17.066667 0 34.133333 13.653333 37.546667 30.72l10.24 160.426667c3.413333 30.72-37.546667 47.786667-58.026667 27.306667a286.378667 286.378667 0 0 0-406.186667 0 286.378667 286.378667 0 0 0 0 406.186666c112.64 112.64 293.546667 112.64 406.186667 0 13.653333-10.24 37.546667-10.24 51.2 3.413334z m-150.186667-334.506667l51.2-6.826667c17.066667-3.413333 30.72-20.48 30.72-37.546666-3.413333-17.066667-20.48-30.72-37.546666-30.72l-51.2 6.826666c-17.066667 3.413333-30.72 20.48-30.72 37.546667 3.413333 17.066667 17.066667 30.72 34.133333 30.72h3.413333z"
                        fill="#a4b2c1"
                        p-id="3314">
                        <animateTransform
                          attributeName="transform"
                          attributeType="XML"
                          type="rotate"
                          from="0 512 512"
                          to="360 512 512"
                          dur="2s"
                          repeatCount="indefinite"
                        />
                      </path>
                    </svg>
                  )}
                  {item.status == LoadStatus.init && (
                    <svg
                      className={styles['icon']}
                      viewBox="0 0 1024 1024"
                      version="1.1"
                      xmlns="http://www.w3.org/2000/svg"
                      p-id="7635"
                      width="200"
                      height="200">
                      <path
                        d="M959.018667 263.274667 683.328 111.637333c-10.282667-5.696-23.296-1.92-28.949333 8.405333-5.696 10.325333-1.92 23.296 8.426667 28.970667l248.938667 136.917333c-3.392 0.021333-6.805333 0.597333-10.005333 2.346667L505.941333 505.941333 122.794667 281.152c-0.362667-0.213333-0.768-0.192-1.130667-0.384L359.466667 149.973333c10.325333-5.674667 14.101333-18.645333 8.426667-28.970667-5.674667-10.304-18.624-14.122667-28.970667-8.405333L64.96 263.274667c-6.805333 3.733333-11.050667 10.901333-11.050667 18.688l0 480.448c0 7.765333 4.245333 14.933333 11.050667 18.688l436.757333 240.256c0.426667 0.234667 0.874667 0.32 1.301333 0.512 0.533333 0.256 1.066667 0.448 1.621333 0.64 2.389333 0.874667 4.864 1.472 7.36 1.472s4.949333-0.597333 7.338667-1.472c0.554667-0.213333 1.109333-0.405333 1.642667-0.64 0.426667-0.213333 0.874667-0.298667 1.301333-0.512l436.757333-240.256c6.805333-3.754667 11.050667-10.922667 11.050667-18.688L970.090667 281.962667C970.090667 274.176 965.845333 267.008 959.018667 263.274667zM96.576 313.792c1.386667 1.514667 2.773333 3.050667 4.629333 4.138667L490.666667 546.432l0 420.117333L96.576 749.781333 96.576 313.792zM533.333333 966.570667 533.333333 539.562667l388.928-213.866667c2.069333-1.130667 3.626667-2.709333 5.141333-4.352l0 428.458667L533.333333 966.570667z"
                        p-id="7636"
                        fill="#a4b2c1"></path>
                      <path
                        d="M344.576 218.538667c-8.341333 8.32-8.341333 21.824 0 30.165333l152.32 152.362667c4.010667 4.010667 9.429333 6.250667 15.082667 6.250667s11.093333-2.24 15.082667-6.250667l152.362667-152.362667c8.341333-8.341333 8.341333-21.824 0-30.165333s-21.824-8.341333-30.165333 0L533.333333 334.442667 533.333333 29.333333c0-11.776-9.536-21.333333-21.333333-21.333333-11.776 0-21.333333 9.557333-21.333333 21.333333l0 305.152-115.925333-115.946667C366.421333 210.197333 352.917333 210.197333 344.576 218.538667z"
                        p-id="7637"
                        fill="#a4b2c1"></path>
                    </svg>
                  )}
                  {item.status == LoadStatus.error && (
                    <svg
                      className={styles['icon']}
                      viewBox="0 0 1024 1024"
                      version="1.1"
                      xmlns="http://www.w3.org/2000/svg"
                      p-id="9809"
                      width="200"
                      height="200">
                      <path
                        d="M955.7 856l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zM480 416c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v184c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V416z m32 352c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48z"
                        p-id="9810"
                        fill="#a1afbf"></path>
                    </svg>
                  )}
                  <Question
                    onClick={(e) => {
                      e.stopPropagation()
                      explainModel(item.name)
                    }}
                  />
                </div>
                {item.status == LoadStatus.loading &&
                  item.progress !== 1 &&
                  item.progress !== 0 && (
                    <div className={styles['load-progress']}>
                      <div
                        className={styles['progress-bar']}
                        style={{
                          width: `${item.progress * 100}%`,
                        }}>
                        <div className={styles['back-color']}></div>
                      </div>
                    </div>
                  )}
              </div>
            )
          })}
        </div>
        <div className={styles['grop-title']}>
          <span>推理分块大小</span>
          <Question onClick={explainBlockSize} />
        </div>
        <div className={styles['grop-content']}>
          <input
            className={styles['range']}
            type="range"
            min="32"
            max="192"
            step="8"
            value={blockSize}
            onChange={(e) => setBlockSize(Number(e.target.value))}></input>
          <span className={styles['range-text']}>
            {blockSize} x {blockSize}
          </span>
        </div>
        <div className={styles['grop-title']}>
          <span>预览图片模式</span>
        </div>
        <div className={styles['grop-content']}>
          {imagePreviewModes.map((item, index) => {
            return (
              <div
                onClick={() => setPreviewMode(item)}
                key={index}
                className={
                  item == previewMode
                    ? styles['choice-btn-active']
                    : styles['choice-btn']
                }>
                {item}
              </div>
            )
          })}
        </div>
        <div className={styles['grop-title']}>
          <span>保存图片类型</span>
        </div>
        <div className={styles['grop-content']}>
          {saveTypes.map((item, index) => {
            return (
              <div
                onClick={() => setSaveType(item)}
                key={index}
                className={
                  styles[item == saveType ? 'choice-btn-active' : 'choice-btn']
                }>
                {item}
              </div>
            )
          })}
        </div>
        {(saveType == 'jpeg' || saveType == 'webp') && (
          <>
            <div className={styles['grop-title']}>
              <span>压缩质量</span>
              <Question onClick={explainCompressionRatio} />
            </div>
            <div className={styles['grop-content']}>
              <input
                className={styles['range']}
                type="range"
                min="0.7"
                max="1"
                step="0.01"
                value={saveCompressionRatio}
                onChange={(e) =>
                  setSaveCompressionRatio(Number(e.target.value))
                }></input>
              <span className={styles['range-text']}>
                {saveCompressionRatio}
              </span>
            </div>
          </>
        )}
        <div style={{ height: '100px' }}></div>
      </div>
    </div>
  )
}
export default ImageUpscaleRightContent
